package project.model;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

public class Mecung extends Observable implements Observer {
    
    public static final int NORTH = 1;
    public static final int EAST  = 2;
    public static final int SOUTH = 3;
    public static final int WEST  = 4;
    
    private AFactory factory;
    private int[][] bando;
    //private Point toaDo;
    private int chieuCao;
    private int chieuRong;
    private Hero tom;
    private HashMap<Integer, ARoom> save;
    private boolean nhapMagicQuestion;
    private String question;

	public Mecung(File file) {
    	factory   = new RoomFactory().getRoomFactory();
    	save      = new HashMap<Integer, ARoom>();
    	//toaDo     = new Point();
    	chieuCao  = 450;
    	chieuRong = 800;
    }
    
    public void heroLogin(Hero hero){
        this.tom = hero;
        this.tom.addObserver(this);
    }
    
    public void duaGiaTriDungeonVao(File file) {
    	try {
			FileInputStream fis = new FileInputStream(file);
			BufferedReader br   = new BufferedReader(new InputStreamReader(fis));

			String strLine;
			int lines = 0;
			List<String> questionList = new ArrayList<String>();
			
			while ((strLine = br.readLine()) != null)   {
				lines++;
				questionList.add(strLine);
			}
			br.close();
			
			Random rand = new Random();
			int line = rand.nextInt(lines);
			question = questionList.get(line);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
    
    public ARoom timPhong(int huong) {
    	ARoom aroom = tom.getVitriHienTai();
    	if(aroom != null){
	    	switch (huong) {
				case NORTH:
					return aroom.getNorth();
				case EAST:
					return aroom.getEast();
				case SOUTH:
					return aroom.getSouth();
				case WEST:
					return aroom.getWest();
			}
    	}
        return null;
    }
    
    public void roomsDuocDuaVao(String[][] rooms) {
    	Random rand = new Random();
		int line = rand.nextInt(rooms.length - 1) + 2;
		//System.out.println((rooms.length - 1) + " - " + line);
		
    	for (int i = 0; i < rooms.length; i++) {
    		String[] room = rooms[i];
    		int index = Integer.parseInt(room[0]);
    		Point point = new Point();
    		ARoom aroom = factory.createRoom(index, point);
    		if(line == i){
    			String[] array = question.split(":");
    			question = array[0];
    			String cauhoi  = array[1];
    			aroom = factory.createMagicRoom(index, point, cauhoi);
    		}
			save.put(index, aroom);
		}
    }
    
    public void roomsLienKetVoiNhau(String[][] rooms) {
    	for (String[] room : rooms) {
    		int index = Integer.parseInt(room[0]);
    		int north = Integer.parseInt(room[NORTH]);
    		int east  = Integer.parseInt(room[EAST]);
    		int south = Integer.parseInt(room[SOUTH]);
    		int west  = Integer.parseInt(room[WEST]);
    		
    		ARoom aroom = save.get(index);
    		aroom.setNorth(save.get(north));
    		aroom.setEast(save.get(east));
    		aroom.setSouth(save.get(south));
    		aroom.setWest(save.get(west));
		}
    }
    
    public void ganGiaTriToaDoRoom(String[][] rooms) {
    	int rong = chieuRong / bando[0].length;
    	int cao  = chieuCao / bando.length;
    	for (int i = 0; i < bando.length; i++) {
			for (int j = 0; j < bando[i].length; j++) {
				int index = bando[i][j];
				if(index > 0){
					ARoom aroom = save.get(index);
					Point point = new Point(j*rong, i*cao);
					aroom.setToaDo(point);
				}
			}
		}
    }
    
    public void toaDoNormal(String[][] rooms) {
    	HashMap<Integer, Point> roomIndex = new HashMap<Integer, Point>();
    	int max_x = 0;
    	int max_y = 0;
    	int min_x = 0;
    	int min_y = 0;
    	
    	for (String[] room : rooms) {
    		int index = Integer.parseInt(room[0]);
    		int north = Integer.parseInt(room[NORTH]);
    		int east  = Integer.parseInt(room[EAST]);
    		int south = Integer.parseInt(room[SOUTH]);
    		int west  = Integer.parseInt(room[WEST]);
    		
    		if(!roomIndex.containsKey(index)){
    			roomIndex.put(index, new Point(0,0));
    		}

			Point point = roomIndex.get(index);
			if(north > 0) roomIndex.put(north, new Point(point.x,   point.y-1));
    		if(east  > 0) roomIndex.put(east,  new Point(point.x+1, point.y));
    		if(south > 0) roomIndex.put(south, new Point(point.x,   point.y+1));
    		if(west  > 0) roomIndex.put(west,  new Point(point.x-1, point.y));
    	}
    	
    	for (String[] room : rooms) {
			int index = Integer.parseInt(room[0]);
    		Point point = roomIndex.get(index);
    		if(max_x < point.x) max_x = point.x;
    		if(max_y < point.y) max_y = point.y;
    		if(min_x > point.x) min_x = point.x;
    		if(min_y > point.y) min_y = point.y;
		}
    	
    	//System.out.println(max_x + "\t" + max_y + "\t" + min_x + "\t" + min_y);
    	int abs_x  = Math.abs(min_x);
    	int abs_y  = Math.abs(min_y);
    	int size_x = Math.abs(max_x) + abs_x + 1;
    	int size_y = Math.abs(max_y) + abs_y + 1;
    	bando = new int[size_y][size_x];
    	
    	for (String[] room : rooms) {
    		int index = Integer.parseInt(room[0]);
    		Point point = roomIndex.get(index);
    		int x = point.x + abs_x;
    		int y = point.y + abs_y;
    		bando[y][x] = index;
		}
    }
    
//    public ARoom getRandomRoom() {
//    	
//        return null;
//    }
    
    public int[][] getBanDoThongMinh() {
        return bando;
    }
    
    public void dichuyen(int huong) {
    	tom.goTo(huong);
    }
    
    public String[][] docFile(File file) {
    	try {
			FileInputStream fis = new FileInputStream(file);
			BufferedReader br 	= new BufferedReader(new InputStreamReader(fis));

			String strLine;
			int lines = 0;
			List<String[]> roomList = new ArrayList<String[]>();
			
			while ((strLine = br.readLine()) != null)   {
				String[] array = strLine.split(":");
				if(array.length == 5){
					lines++;
					roomList.add(array);
				}
			}
			br.close();
			
			String[][] rooms = new String[lines][];
			for (int i = 0; i < roomList.size(); i++) {
				rooms[i] = roomList.get(i);
			}
			return rooms;
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    	return null;
    }
    
    public Hero getHero() {
        return this.tom;
    }
    
    public ARoom getRoomTheoNumber(int num) {
        return num > 0 ? save.get(num) : null;
    }
    
    @Override
    public void update(Observable observable, Object object) {
    	if (observable == tom)
        {
           int huong = tom.getHuongMongMuonDiDen();
           ARoom aroom = timPhong(huong);
           if(aroom != null){
               setChanged();
               notifyObservers();
           }
        }
    }
    
    public void xedichHero(ARoom room1, ARoom room2) {
        tom.setVitriHienTai(room2);
        room2.goInRoom(tom);
        if(room2.isVisitorInRoom()){
        	room1.setVisitor(null);
        }
        //System.out.println(room1.isVisitorInRoom() + " - " + room1.getRoomNr());
        //System.out.println(room2.isVisitorInRoom() + " - " + room2.getRoomNr());
    }
    
    public boolean magicQuestionCoDuocDuaVaoKhong() {
        return this.nhapMagicQuestion;
    }
    
    public void setMagicQuestion(boolean magic) {
        this.nhapMagicQuestion = magic;
    }

	public int getChieuCao() {
		return chieuCao;
	}

	public void setChieuCao(int chieuCao) {
		this.chieuCao = chieuCao;
	}

	public int getChieuRong() {
		return chieuRong;
	}

	public void setChieuRong(int chieuRong) {
		this.chieuRong = chieuRong;
	}
	
    public String getQuestion() {
		return question;
	}

	public void setQuestion(String question) {
		this.question = question;
	}
}
